#include "wifimonitor.h"
#include "qnetman2.h"

#include <QtGlobal>
#include <QtDeclarative>



WiFiListData::WiFiListData( QObject *_parent, QNMSettings * qset) : QObject(_parent), parent( _parent )
{
    Q_UNUSED( qset );
}

void WiFiListData::initListWiFiData()
{
    QList< Map >* listWiFiData = WiFiMonitor::__listWiFiData;
    if( listWiFiData == NULL ) {
        return;
    }

    listModel = new WiFiListModel( this );

    bool flValue0 = false;
    QString mac0, channel0, essid0, chFreq0, encPic0;
    QList< Map >::const_iterator itr;
    for ( itr = listWiFiData->constBegin(); itr != listWiFiData->constEnd(); itr++ )
    {
        Map pQMapData = *itr;

        QString mac = (pQMapData["mac"]).toString();
        QString channel = (pQMapData["channel"]).toString();
        QString essid = (pQMapData["essid"]).toString();
        QString level_dBm = (pQMapData["level"]).toString();
        QString level_per = (pQMapData["quality"]).toString();
        QString chFreq = (pQMapData["frequency"]).toString();

        QString encrypt("open");
        QString encryptPic("/opt/QNetMan2/qml/QNetMan2/pictures/wifi_open.png");
        if( pQMapData.contains("encrypt") ) {
            if( (pQMapData["encrypt"]).toBool() ) {
                if( pQMapData.contains("wpa")  ) {
                    encrypt = "wpa2";
                    encryptPic = "/opt/QNetMan2/qml/QNetMan2/pictures/wifi_wpa.png";
                } else if( pQMapData.contains("wpa2") ) {
                    encrypt = "wpa";
                    encryptPic = "/opt/QNetMan2/qml/QNetMan2/pictures/wifi_wpa.png";
                } else {
                    encrypt = "wep";
                    encryptPic = "/opt/QNetMan2/qml/QNetMan2/pictures/wifi_wep.png";
                }
            }
        }

        if( !flValue0 ) {
            flValue0 = true;
            mac0 = mac;
            channel0 = channel;
            essid0 = essid;
            chFreq0 = chFreq;
            encPic0 = encryptPic;
        }

        //qDebug()<<"initListWiFiData():" << essid << " " << level_per;
        //WiFiItemModel *item = new WiFiItemModel( essid, channel, mac, level_dBm, level_per, encrypt, encryptPic );
        listModel->append( essid, channel, mac, level_dBm, level_per, encrypt, encryptPic, chFreq );
        //listModel->append( item );
    }

    QDeclarativeView *qmlObj = (QDeclarativeView*)(this->parent);
    QDeclarativeEngine *engine = qmlObj->engine();
    engine->rootContext()->setContextProperty( "cppListWiFiData", listModel );

    engine->rootContext()->setContextProperty( "cppMac0", mac0 );
    engine->rootContext()->setContextProperty( "cppChannel0", channel0 );
    engine->rootContext()->setContextProperty( "cppEssid0", essid0 );
    engine->rootContext()->setContextProperty( "cppFreq0", chFreq0 );
    engine->rootContext()->setContextProperty( "cppEncPic0", encPic0 );
    //qDebug()<<"----------------------------";
}


/*-------------------------------------------------------------------------*/
QList< Map >* WiFiMonitor::__listWiFiData = NULL;
/*-------------------------------------------------------------------------*/


WiFiMonitor::WiFiMonitor(QDeclarativeItem *parent) : QDeclarativeItem(parent)
{
    this->setFlag( QDeclarativeItem::ItemHasNoContents, false );

    qset_here = new QNMSettings( this );

    timeout = 3;
    timer.setInterval( timeout*1000 );
    QObject::connect( &timer, SIGNAL(timeout()), this, SLOT(updateWiFiData()) );

    iface = "wlan0";

    /* размеры графика в ландшафтном режиме */
    LX_l = 845; LY_l = 380;
    /* размеры графика в портретном режиме */
    LX_p = 470; LY_p = 735;

    shiftX = 10; lenghtX = LX_l;
    shiftY = 20; lenghtY = LX_p;

    /* длина графика по Y */
    Ly = lenghtX - shiftX;
    /* длина графика по X */
    Lx = lenghtY - shiftY;

    /* ширина линии графика */
    pxLenGraph = 4;

    /* кисть и шрифт сетки */
    penGrid.setColor( QColor(90,90,90) );
    penGrid.setWidth(1);
    penGrid.setStyle( Qt::DashLine );
    fontGrid.setPointSize( 12 );

    /* кисть и шрифт системы координат */
    penSC.setColor( QColor("gray") );
    penSC.setWidth( 4 );

    wifiData = new WiFiData(this);
    QObject::connect( wifiData, SIGNAL(dataReady(bool)), this, SLOT(getWiFiData(bool)));
    QObject::connect( wifiData, SIGNAL(dataError()), this, SLOT(getWiFiError()));

    /* вся ширина канала отображаемая на графике = 100 МГц
     * Каждый канал отстоит на определенное значение от левого края, которое храниться в списке
     */
    listShiftWiFiChannel.append(11);
    listShiftWiFiChannel.append(16);
    listShiftWiFiChannel.append(21);
    listShiftWiFiChannel.append(26);
    listShiftWiFiChannel.append(31);
    listShiftWiFiChannel.append(36);
    listShiftWiFiChannel.append(41);
    listShiftWiFiChannel.append(46);
    listShiftWiFiChannel.append(51);
    listShiftWiFiChannel.append(56);
    listShiftWiFiChannel.append(61);
    listShiftWiFiChannel.append(66);
    listShiftWiFiChannel.append(71);
    listShiftWiFiChannel.append(83);

    /* ширина WiFi канала */
    bandWiFiChannel = 22; //MHz

    /* ширина всего экрана в МГц */
    widthMHz = 95.0;

    /* список цветов для графиков */
    clr00_10 = new QColor("#3333ff");
    clr10_20 = new QColor("#ff0000");
    clr20_30 = new QColor("#ff8000");
    clr30_40 = new QColor("#9696c8");
    clr40_50 = new QColor("#ffff00");
    clr50_60 = new QColor("#ffffa0");
    clr60_70 = new QColor("#548a54");
    clr70_80 = new QColor("#64b48c");
    clr80_90 = new QColor("#808080");
    clr90_99 = new QColor("#c8c8c8");


    isUpdateRunning = false;

}

WiFiMonitor::~WiFiMonitor()
{
    if( clr00_10 ) delete clr00_10;
    if( clr10_20 ) delete clr10_20;
    if( clr20_30 ) delete clr20_30;
    if( clr30_40 ) delete clr30_40;
    if( clr40_50 ) delete clr40_50;
    if( clr50_60 ) delete clr50_60;
    if( clr60_70 ) delete clr60_70;
    if( clr70_80 ) delete clr70_80;
    if( clr80_90 ) delete clr80_90;
    if( clr90_99 ) delete clr90_99;
}


void WiFiMonitor::paint(QPainter *paint, const QStyleOptionGraphicsItem *options, QWidget *widget)
{
    Q_UNUSED( options );
    Q_UNUSED( widget );

    Ly = lenghtY - shiftY;
    Lx = lenghtX - shiftX;

    paint->setRenderHints( QPainter::Antialiasing, true );

    //фон
    //paint->setPen( QColor("gray") );
    //paint->setBrush( QColor("black") );
    //paint->drawRect(0, 0, lenghtX, lenghtY );

    this->drawWiFiSpectrum( paint );
}

/* ============= функции отрисовки ============= */
void WiFiMonitor::drawSystemCoord( QPainter* paint )
{
    paint->setPen( penSC );

    paint->drawLine( shiftX, lenghtY-shiftY, lenghtX, lenghtY-shiftY );
    paint->drawLine( shiftX, 0, shiftX, lenghtY-shiftX );
}

void WiFiMonitor::drawGrid( QPainter* paint )
{
    paint->setPen( penGrid );
    paint->setFont( fontGrid );

    int partY = 10;
    float stepLineY = (float)Ly / (float)(partY); /* шаг горизонтально (по оси Y) линии сетки */
    float it = 0.0;
    float currY = (float)Ly;
    QString txt("");
    while( it < (partY+1) )
    {
        paint->drawLine( shiftX, Ly-currY, lenghtX, Ly-currY );

        int i_it = (int)it;
        txt.sprintf("%d%%", i_it*10);
        if( i_it%2 == 0 ) {
            paint->drawText( shiftX+5, currY+12, txt );
        }

        currY = currY - stepLineY;
        it += 1.0;
    }

    for( int i=0; i<listShiftWiFiChannel.length(); i++ )
    {
        float Xi = (float)listShiftWiFiChannel.at(i) * Lx / widthMHz ;
        //qDebug() << (float)listShiftWiFiChannel.at(i) << Xi << Lx;
        paint->drawLine( Xi+shiftX, 0, Xi+shiftX, Ly );
        txt.sprintf("%d", (i+1));
        paint->drawText( shiftX+Xi-5, Ly+18, txt );
    }

    paint->drawText( Lx-50, Ly-10, QString("Channel") );
}

void WiFiMonitor::drawWiFiSpectrum( QPainter* paint )
{
    /* отрисовка системы координат и прочей аттрибутики */
    this->drawSystemCoord( paint );
    this->drawGrid( paint );

    /* отрисовка спектров WiFi сигналов */
    QFont font;
    font.setPointSize( 12 );
    paint->setFont( font );

    if( !flDataExists ) {
        QBrush br( QColor("red") );
        paint->setBrush(br);
        paint->drawText( Lx-50, 15, QString("No data") );
        return;
    }

    int nColor = 0;
    QList< Map >::const_iterator itr;
    for( itr = listWiFiData.constBegin(); itr != listWiFiData.constEnd(); itr++ )
    {
        Map pQMapData = *itr;

        float quality = (pQMapData["quality"]).toFloat();

        QColor *clr = this->colorLevel( quality );

        //QColor clr( listColorGraph.at( (nColor%listColorGraph.length()) ) );

        QPen pen(*clr, 0);
        pen.setWidth(2);
        paint->setPen(pen);

        clr->setAlpha(45);
        QBrush br(*clr);
        paint->setBrush(br);
        clr->setAlpha(255);

        nColor++;


        int channel = (pQMapData["channel"]).toInt();
        if( (channel > 14) || (channel < 1) ) {
            continue;
        }

        float Xi = (float)listShiftWiFiChannel.at( (channel-1) ) * Lx / widthMHz ;
        float y = Ly*quality;
        paint->drawLine( Xi+shiftX, Ly, Xi+shiftX, Ly-y );

        QString txt = (pQMapData["essid"]).toString();

        txt += QString(" (-") + (pQMapData["level"]).toString() + QString(" dBm)");
        paint->drawText( shiftX+Xi-20, Ly-y-10, txt );

        /* рисуем спектр сигнала */
        int _band = (Lx / widthMHz) * bandWiFiChannel;
        int x_arc = (shiftX + Xi) - _band/2;
        int y_arc = (Ly-y);
        paint->setBackgroundMode(Qt::OpaqueMode);
        paint->drawPie(x_arc, y_arc, _band, 2*y, 0, 180*16);
        paint->setBackgroundMode(Qt::TransparentMode);
        paint->drawArc(x_arc, y_arc, _band, 2*y, 0, 180*16);
        //qDebug() << channel << "=>" << quality << "("<<(Xi+shiftX)<<Ly<<(Xi+shiftX)<<(Ly*quality)<<")";

        if( pQMapData.contains("encrypt") ) {
            QPixmap *encrypt_pic = NULL;
            if( (pQMapData["encrypt"]).toBool() ) {
                /* сеть зашифрована */
                if( pQMapData.contains("wpa") || pQMapData.contains("wpa2") ) {
                     encrypt_pic = new QPixmap( QString("/opt/QNetMan2/qml/QNetMan2/pictures/wlan_wpa.png")  );
                } else {
                    encrypt_pic = new QPixmap( QString("/opt/QNetMan2/qml/QNetMan2/pictures/wlan_wep.png")  );
                }
            } else {
                /* свободная сеть */
                encrypt_pic = new QPixmap( QString("/opt/QNetMan2/qml/QNetMan2/pictures/wlan_open.png")  );
            }

            paint->drawPixmap(shiftX+Xi-42, Ly-y-25, 22, 20, *encrypt_pic );
            if( encrypt_pic != NULL ) delete encrypt_pic;
        } else {
            /* ? */
            QPixmap encrypt_pic( QString("/opt/QNetMan2/qml/QNetMan2/pictures/wlan_open.png")  );
            paint->drawPixmap(shiftX+Xi-42, Ly-y-25, 22, 20, encrypt_pic );
        }
    }

}
/* ================================================= */

void WiFiMonitor::getWiFiError()
{
    flDataExists = false;
    isUpdateRunning = false;
    emit updateStatusChange();
}

/* слот, вызывается когда получены новые данные */
void WiFiMonitor::getWiFiData(bool _flDataExists)
{
    /* очистка от предыдущих значений */
    QList< Map >::iterator itr = listWiFiData.begin();
    while (itr != listWiFiData.end())
    {
        listWiFiData.erase(itr);
        itr++;
    }

    listWiFiData.clear(); //wtf

    flDataExists = _flDataExists;
    /* забираем данные у объекта, получившего данные о wifi сетях */
    if( _flDataExists ) {
        listWiFiData = wifiData->getData();
        __listWiFiData = &listWiFiData;
    }

    emit changeValueParam();

    this->hide();
    this->show();

    isUpdateRunning = false;
    emit updateStatusChange();

}

/* вызывается из QML для обновления данных вручную */
void WiFiMonitor::updateWiFiData()
{
    if(  isUpdateRunning ) { return; }

    isUpdateRunning = true;
    emit updateStatusChange();

    //qDebug() << "WiFiMonitor::updateWiFiData()";

    /* запрашиваем обновления данных в объекте wifiData */
    wifiData->requestWiFiData( iface );
}

QColor *WiFiMonitor::colorLevel( const float quality ) const
{
    QColor *clr = NULL;
    if( quality < 0.1 ) {
        clr = this->clr00_10;
    } else if( (quality >= 0.1) && (quality < 0.2) ) {
        clr = this->clr10_20;
    } else if( (quality >= 0.2) && (quality < 0.3) ) {
        clr = this->clr20_30;
    } else if( (quality >= 0.3) && (quality < 0.4) ) {
        clr = this->clr30_40;
    } else if( (quality >= 0.4) && (quality < 0.5) ) {
        clr = this->clr40_50;
    } else if( (quality >= 0.5) && (quality < 0.6) ) {
        clr = this->clr50_60;
    } else if( (quality >= 0.6) && (quality < 0.7) ) {
        clr = this->clr60_70;
    } else if( (quality >= 0.7) && (quality < 0.8) ) {
        clr = this->clr70_80;
    } else if( (quality >= 0.8) && (quality < 0.9) ) {
        clr = this->clr80_90;
    } else if( quality >= 0.9 ) {
        clr = this->clr90_99;
    }
    return clr;
}


// на будущее
void WiFiMonitor::timerStart()
{
    this->initSettings();
    timer.start();
}

void WiFiMonitor::timerStop()
{
    timer.stop();
}

void WiFiMonitor::initSettings()
{
}




